﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using ZedGraph;
using System.Threading;

namespace fes
{
  public partial class MainWindow : Form
  {
    private StockData sd = new StockData();
    private StringRedir RedirConsole;
    private TextWriter ConsoleWriter;
    private String testDataFile;
    private NNStockMarket n;
    private bool nauczonoSiec;
    private int teachingSessions = 0;
    

    public MainWindow()
    {
#if DEBUG
#else
        Thread th = new Thread(new ThreadStart(DoSplash));
        th.Start();
        Thread.Sleep(3000);
        th.Abort();
        Thread.Sleep(1000);
#endif

      InitializeComponent();

      // Here we redirect Console.WriteLine to a RichTextBox control. 
      ConsoleWriter = Console.Out;	// Save the current console TextWriter. 
      RedirConsole = new StringRedir(ref rtbLogger);
      Console.SetOut(RedirConsole);	// Set console output to the StringRedir class.

      GraphPane myPane = priceChart.GraphPane;
      myPane.Title.Text = "Wykres ceny";
      myPane.XAxis.Title.Text = "Data";
      myPane.YAxis.Title.Text = "Cena [PLN]";
      myPane = profitChart.GraphPane;
      myPane.Title.Text = "Wartość portfela";
      myPane.XAxis.Title.Text = "Data";
      myPane.YAxis.Title.Text = "Wartość [PLN]";
      nauczonoSiec = false;
    }

    private void DoSplash() 
    {
        SplashScreen sp = new SplashScreen();
        sp.ShowDialog();
    }

    private void exitToolStripMenuItem_Click(object sender, EventArgs e)
    {
      Application.Exit();
    }
    private void Form1_Load(object sender, EventArgs e)
    {

        OurGlobals.MyExpertSystem = new ExpertSystem("Main");

        //if (File.Exists("Default.neural")) n = new NNStockMarket("Default.neural");
        //else n = new NNStockMarket(2, 3);
    }

    private void initPriceGraph(string symbol, DateTime startDate, DateTime endDate)
    {
      if (priceChart.GraphPane.CurveList.Count == 1)
        priceChart.GraphPane.CurveList.RemoveAt(0);
      GraphPane myPane = priceChart.GraphPane;
      // show the horizontal scroll bar
      priceChart.IsShowHScrollBar = true;
      // Disable the AutoScrollRange option (because we have set the scroll range manually)
      priceChart.IsAutoScrollRange = false;
      // Horizontal pan and zoom allowed
      priceChart.IsEnableHPan = true;
      priceChart.IsEnableHZoom = true;
      // Vertical pan and zoom not allowed
      priceChart.IsEnableVPan = false;
      priceChart.IsEnableVZoom = false;
      priceChart.GraphPane.IsBoundedRanges = true;
      // Use DateAsOrdinal to skip weekend gaps
      myPane.XAxis.Type = AxisType.DateDual;
      //myPane.XAxis.Type = AxisType.Date;
      // pretty it up a little
      myPane.Chart.Fill = new Fill(Color.White, Color.LightGoldenrodYellow, 45.0f);
      myPane.Fill = new Fill(Color.White, Color.FromArgb(220, 220, 255), 45.0f);
      // Set the title and axis labels   
      myPane.Title.Text = symbol;
      StockPointList spl = new StockPointList();
      myPane.Legend.IsVisible = false;
      JapaneseCandleStickItem myCurve = myPane.AddJapaneseCandleStick("trades", spl);
      myCurve.Stick.IsAutoSize = true;
      myCurve.Stick.Color = Color.Black;
      // manually set the scroll range
      priceChart.ScrollMinX = new XDate(startDate).XLDate;
      priceChart.ScrollMaxX = new XDate(endDate).XLDate + 2;
      myPane.XAxis.Scale.Min = priceChart.ScrollMaxX - 100;
      myPane.XAxis.Scale.Max = priceChart.ScrollMaxX;
      // Tell ZedGraph to calculate the axis ranges
      priceChart.AxisChange();
      priceChart.Invalidate();
      priceChart.Refresh();
    }

    private void initProfitGraph(string symbol, DateTime startDate, DateTime endDate)
    {
      if (profitChart.GraphPane.CurveList.Count == 1)
        profitChart.GraphPane.CurveList.RemoveAt(0);
      GraphPane myPane = profitChart.GraphPane;
      // show the horizontal scroll bar
      profitChart.IsShowHScrollBar = true;
      // Disable the AutoScrollRange option (because we have set the scroll range manually)
      profitChart.IsAutoScrollRange = false;
      // Horizontal pan and zoom allowed
      profitChart.IsEnableHPan = true;
      profitChart.IsEnableHZoom = true;
      // Vertical pan and zoom not allowed
      profitChart.IsEnableVPan = false;
      profitChart.IsEnableVZoom = false;
      profitChart.GraphPane.IsBoundedRanges = true;
      // Use DateAsOrdinal to skip weekend gaps
      myPane.XAxis.Type = AxisType.DateDual;
      myPane.YAxis.Scale.Mag = 0;
      // pretty it up a little
      myPane.Chart.Fill = new Fill(Color.White, Color.LightGoldenrodYellow, 45.0f);
      myPane.Fill = new Fill(Color.White, Color.FromArgb(220, 220, 255), 45.0f);
      // Set the title and axis labels   
      myPane.Title.Text = symbol;
      myPane.Legend.IsVisible = false;
      PointPairList ppl = new PointPairList();
      LineItem myCurve = myPane.AddCurve("profit", ppl, Color.Red, SymbolType.None);
      // manually set the scroll range
      profitChart.ScrollMinX = new XDate(startDate).XLDate;
      profitChart.ScrollMaxX = new XDate(endDate).XLDate + 2;
      myPane.XAxis.Scale.Min = profitChart.ScrollMaxX - 100;
      myPane.XAxis.Scale.Max = profitChart.ScrollMaxX;
      // Tell ZedGraph to calculate the axis ranges
      profitChart.AxisChange();
      profitChart.Invalidate();
      profitChart.Refresh();
    }

    private void addNewCandle(DateTime dt, double h, double l, double o, double c, double v)
    {
      JapaneseCandleStickItem curve = priceChart.GraphPane.CurveList[0] as JapaneseCandleStickItem;

      IPointListEdit list = curve.Points as IPointListEdit;

      StockPt sp = new StockPt(new XDate(dt).XLDate, h, l, o, c, v);

      list.Add(sp);

      priceChart.GraphPane.XAxis.Scale.Min = new XDate(dt).XLDate - 100;
      priceChart.GraphPane.XAxis.Scale.Max = new XDate(dt).XLDate + 2;

      priceChart.AxisChange();
      priceChart.Invalidate();
    }

    private void addNewProfitPoint(DateTime dt, double value)
    {
      LineItem curve = profitChart.GraphPane.CurveList[0] as LineItem;

      IPointListEdit list = curve.Points as IPointListEdit;

      list.Add(new XDate(dt).XLDate, value);

      profitChart.GraphPane.XAxis.Scale.Min = new XDate(dt).XLDate - 100;
      profitChart.GraphPane.XAxis.Scale.Max = new XDate(dt).XLDate + 2;

      profitChart.AxisChange();
      profitChart.Invalidate();

    }

    private void neuron_Click(object sender, EventArgs e)
    {
      ExpertSet ExSet = new ExpertSet();
      if (!OurGlobals.MyExpertSystem.IsSet)
      {
        ExSet.ShowDialog();
        if (!OurGlobals.MyExpertSystem.IsSet)
          return;
      }

      teachingSessions = ExSet.getNumberOfTeachingSessions();

      StockData sd = OurGlobals.teachingSD;
      for (int i = ExSet.getNumberOfTeachingSessions(); i >= 0; i--)
      {
        //TODO: uczenie sieci, ktore jest zakomentowane nizej powinno byc zaimplementowane w metodzie PushNextData()
          OurGlobals.MyExpertSystem.PushNextData(sd.getSymbol(),
            sd.getDateToLast(i), sd.getOpenToLast(i), sd.getHighToLast(i),
            sd.getLowToLast(i), sd.getCloseToLast(i), sd.getVolToLast(i));
      }

      // price graph initialization and painting
      sd.Rewind();
      initPriceGraph(sd.getSymbol(), sd.getFirstDate(), sd.getLastDate());
      initProfitGraph("Wartość portfela", sd.getFirstDate(), sd.getLastDate());

      int j = 0;
      while(sd.getNext() != -1)
      {
        addNewCandle(sd.getDate(), sd.getHigh(), sd.getLow(), sd.getOpen(), sd.getClose(), sd.getVol());
        if (0 == j % 100)
        {
          pb.Value = 100 * j / sd.getSize();
          priceChart.Refresh();
        }
        j++;
      }
      pb.Value = 100;
      OurGlobals.MyExpertSystem.IsTeached = true;
      Console.WriteLine("Uczenie sieci zakończone");
      /*
      StockData sd = OurGlobals.teachingSD;
      sd.readFromFile(testDataFile);


      //NeuralNet n = new NeuralNet("../../siecneuronowa.xml");
     // NNStockMarket n = new NNStockMarket(2, 3);

      FuzzyValue ROCind = new FuzzyValue("ROC");
      FuzzyValue CCIind = new FuzzyValue("CCI");
      FuzzyValue RSIind = new FuzzyValue("RSI");
      FuzzyValue MFIind = new FuzzyValue("MFI");
      FuzzyValue IMIind = new FuzzyValue("IMI");
      FuzzyValue CMOind = new FuzzyValue("CMO");

      Dictionary<String, Object> IndParams = new Dictionary<string, object>();
      IndParams.Add("n", 5);

      ROC ROCindicator = new ROC(IndParams);
      CCI CCIindicator = new CCI(IndParams);
      RSI RSIindicator = new RSI(IndParams);
      MFI MFIindicator = new MFI(IndParams);
      IMI IMIindicator = new IMI(IndParams);
      CMO CMOindicator = new CMO(IndParams);

      ROCind.addFuzzySet(new double[2] { -15.0, -7.5 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
      ROCind.addFuzzySet(new double[3] { -10.0, 0.0, 10.0 }, "M", FuzzySet.FuzzySetType.Triangle);
      ROCind.addFuzzySet(new double[2] { 7.5, 15.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);

      CCIind.addFuzzySet(new double[2] { -150.0, -50.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
      CCIind.addFuzzySet(new double[3] { -125.0, 0.0, 125.0 }, "M", FuzzySet.FuzzySetType.Triangle);
      CCIind.addFuzzySet(new double[2] { 50.0, 150.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);

      RSIind.addFuzzySet(new double[2] { 30.0, 45.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
      RSIind.addFuzzySet(new double[3] { 25.0, 50.0, 75.0 }, "M", FuzzySet.FuzzySetType.Triangle);
      RSIind.addFuzzySet(new double[2] { 55.0, 70.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);

      MFIind.addFuzzySet(new double[2] { 0.0, 20.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
      MFIind.addFuzzySet(new double[3] { 15.0, 50.0, 85.0 }, "M", FuzzySet.FuzzySetType.Triangle);
      MFIind.addFuzzySet(new double[2] { 80.0, 100.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);

      IMIind.addFuzzySet(new double[2] { 0.0, 30.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
      IMIind.addFuzzySet(new double[3] { 25.0, 50.0, 75.0 }, "M", FuzzySet.FuzzySetType.Triangle);
      IMIind.addFuzzySet(new double[2] { 70.0, 100.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);

      CMOind.addFuzzySet(new double[2] { -100.0, -50.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
      CMOind.addFuzzySet(new double[3] { -75.0, 0.0, 75.0 }, "M", FuzzySet.FuzzySetType.Triangle);
      CMOind.addFuzzySet(new double[2] { 50.0, 100.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);

      int end = (int)IndParams["n"];

      //inicjalizacja wykresu
      initPriceGraph(sd.getSymbol(), sd.getFirstDate(), sd.getLastDate());
      initProfitGraph("Wartość portfela", sd.getFirstDate(), sd.getLastDate());

      for (int k = 0; ((k < end) && (sd.getNext() != -1)); k++)
      {
        ROCindicator.pushNextDayData(sd.getOpen(), sd.getHigh(), sd.getLow(), sd.getClose(), sd.getVol());
        CCIindicator.pushNextDayData(sd.getOpen(), sd.getHigh(), sd.getLow(), sd.getClose(), sd.getVol());
        RSIindicator.pushNextDayData(sd.getOpen(), sd.getHigh(), sd.getLow(), sd.getClose(), sd.getVol());
        addNewCandle(sd.getDate(), sd.getHigh(), sd.getLow(), sd.getOpen(), sd.getClose(), sd.getVol());
      }

      //n = new NNStockMarket(neuralNetFile);
      n.initPrize = sd.getClose();
      int iter = 0;
      int bad = 0, good = 0;
      int  i = 0;
      double pbSize = (sd.getSize() - end - 1) / 100.0;
      
      n.BestEffort = 0.1;
      n.WorstEffort = -0.1;
      n.Sensitivity = 0.8;

      while ((sd.getNext() != -1) && (iter < 100))
      {
        i++;
        addNewCandle(sd.getDate(), sd.getHigh(), sd.getLow(), sd.getOpen(), sd.getClose(), sd.getVol());
        ROCindicator.pushNextDayData(sd.getOpen(), sd.getHigh(), sd.getLow(), sd.getClose(), sd.getVol());
        CCIindicator.pushNextDayData(sd.getOpen(), sd.getHigh(), sd.getLow(), sd.getClose(), sd.getVol());
        RSIindicator.pushNextDayData(sd.getOpen(), sd.getHigh(), sd.getLow(), sd.getClose(), sd.getVol());

         

        ROCind.fuzzify(ROCindicator.getValue());
        CCIind.fuzzify(CCIindicator.getValue());
        RSIind.fuzzify(RSIindicator.getValue());

        FuzzyAssociativeMemory fam1 = new FuzzyAssociativeMemory(ROCind, CCIind);
        FuzzyAssociativeMemory fam2 = new FuzzyAssociativeMemory(CCIind, RSIind);
        fam1.reason();
        fam2.reason();
        n.Teach(sd.getClose(),sd.getClose(2), fam1.defuzzify(), fam2.defuzzify());

        if (((n.getChange < 0) && (n.getDecision < 0)) || ((n.getChange >= 0) && (n.getDecision >= 0)))
        {
          if (0 == i % 100)
          {
            //Operacje we-wy sa bardzo kosztowne
            Console.WriteLine("+ :: Zysk rzeczywisty: {0} %  a decyzja sieci: {1} - była dobra (wagi bez zmian). Dobre/złe :{2}/{3}", n.getChange * 100, n.getDecision, good,bad);
          }
          good++;
        }
        else
        {
          if (0 == i % 100)
          {
            Console.WriteLine("- :: Zysk rzeczywisty: {0} %  a decyzja sieci: {1} - była zła (zmiana wag). Dobre/złe  :{2}/{3}", n.getChange * 100, n.getDecision, good,bad);
          }
          bad++;
        }

        int pbValue = (int) (i / pbSize);
        if (pbValue <= 100)
          pb.Value = pbValue;
        //iter++;

      }
      Console.WriteLine("----------------------------------\r\n " +
                        " Sieć nauczona. Bilans: \r\n " +
                        " Dobrych: {0} / Złych: {1}" +
                        "-----------------------------------", good, bad);
      n.SaveNeuralNet(sd.getSymbol() + ".neural");
      nauczonoSiec = true;
      */
    }

    private void zgc_ScrollEvent(object sender, ScrollEventArgs e)
    {
      priceChart.AxisChange();
      priceChart.Invalidate();
      profitChart.GraphPane.XAxis.Scale.Min = priceChart.GraphPane.XAxis.Scale.Min;
      profitChart.GraphPane.XAxis.Scale.Max = priceChart.GraphPane.XAxis.Scale.Max;
      profitChart.AxisChange();
      profitChart.Invalidate();
    }

    ~MainWindow()
    {
      Console.SetOut(ConsoleWriter);	// Redirect Console back to original TextWriter. 
      RedirConsole.Close();			// Close our StringRedir TextWriter. 
    }

    private void btnTest_Click(object sender, EventArgs e)
    {
      if (!OurGlobals.MyExpertSystem.IsTeached)
      {
        MessageBox.Show("Przed symulacją należy przeprowadzić uczenie sieci", "Inwestor giełdowy", MessageBoxButtons.OK, MessageBoxIcon.Information);
        return;
      }
      OurGlobals.MyExpertSystem.newSimulation();

      // aktualizacja stanu portfela i wykresu
      try
      {
        if (!OurGlobals.MyExpertSystem.IsSet)
          return;

        int min = OurGlobals.symbolsSD[0].getSize();
        initProfitGraph("Wartość portfela", OurGlobals.teachingSD.getFirstDate(), OurGlobals.teachingSD.getLastDate());
        foreach (StockData sd in OurGlobals.symbolsSD)
        {
          if (sd.getSize() < min)
            min = sd.getSize();
        }
        if (min > teachingSessions)
          min = teachingSessions;

        int c = min;
        for (int i = c; i >= 0; i--)
        {
          foreach (StockData sd in OurGlobals.symbolsSD)
          {
            double r = OurGlobals.MyExpertSystem.PushNextDataForSym(sd.getSymbol(),
                sd.getDateToLast(i), sd.getOpenToLast(i), sd.getHighToLast(i),
                sd.getLowToLast(i), sd.getCloseToLast(i), sd.getVolToLast(i));
            // Console.WriteLine("r: " + r.ToString());
          }
          OurGlobals.MyExpertSystem.updatePortfolio(dgdPositions);
          addNewProfitPoint(OurGlobals.symbolsSD[0].getDateToLast(i), OurGlobals.MyExpertSystem.getPortfolioValue());
          pb.Value = 100 * (c - i) / c;
          if (0 == i % 100)
          {
            dgdPositions.Refresh();
            profitChart.Refresh();
          }
        }
        pb.Value = 100;
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }

      lblEndPortfolioValue.Text = "Końcowa wartość portfela: " + OurGlobals.MyExpertSystem.getPortfolioValue() + "PLN";
      lblPL.Text = "Zysk/Strata: " + OurGlobals.MyExpertSystem.getProfit() +"%";
      //lblBuyHold.Text = "Strategia Buy && Hold: " + Math.Round(((sd.getLastClose() - sd.getCloseForDay((int)IndParams["n"])) / sd.getCloseForDay((int)IndParams["n"]) * 100), 2) + "%";      


      Console.WriteLine("\n\nDane dotyczące pozostałych strategii:");
      foreach (StockData d in OurGlobals.symbolsSD)
      {
          Best b;
          b = OurGlobals.MyExpertSystem.BestStrategy(d.getSymbol());
          Console.WriteLine("\tDla instrumentu {0} najlepsza strategia to kupić akcje {1} za {2} i sprzedać {3} za {4} z zyskiem {5} %",
                             d.getSymbol(), b.Buy.XTime, b.Buy.XValue, b.Sell.XTime, b.Sell.XValue, Math.Round(b.Profit, 2));
          Console.WriteLine("\tDla instrumentu {0} strategia Buy N Hold: {1} % zysku",
                             d.getSymbol(), Math.Round(OurGlobals.MyExpertSystem.BuyNHoldStrategy(d.getSymbol()),2));
      }
      /*
      if (nauczonoSiec == false)
      {
          OpenFileDialog d = new OpenFileDialog();
          d.Title = "Wybierz zestaw treningowy";
          d.InitialDirectory = Directory.GetCurrentDirectory() + "\\test";
          d.Filter = "Pliki MST (*mst)|*.mst";
          if (d.ShowDialog() != DialogResult.OK)
              return;

          testDataFile = d.FileName;

      }
      double initialCash = 10000.0;
      double cash = initialCash;
      int sharesNumber = 0;
      FuzzyValue ROCind = new FuzzyValue("ROC");
      FuzzyValue CCIind = new FuzzyValue("CCI");
      FuzzyValue RSIind = new FuzzyValue("RSI");
      while (dgvPositions.Rows.Count < 2)
        dgvPositions.Rows.Add();

      Dictionary<String, Object> IndParams = new Dictionary<string, object>();
      IndParams.Add("n", 5);

      ROC ROCindicator = new ROC(IndParams);
      CCI CCIindicator = new CCI(IndParams);
      RSI RSIindicator = new RSI(IndParams);

      ROCind.addFuzzySet(new double[2] { -15.0, -7.5 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
      ROCind.addFuzzySet(new double[3] { -10.0, 0.0, 10.0 }, "M", FuzzySet.FuzzySetType.Triangle);
      ROCind.addFuzzySet(new double[2] { 7.5, 15.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);

      CCIind.addFuzzySet(new double[2] { -150.0, -50.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
      CCIind.addFuzzySet(new double[3] { -125.0, 0.0, 125.0 }, "M", FuzzySet.FuzzySetType.Triangle);
      CCIind.addFuzzySet(new double[2] { 50.0, 150.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);

      RSIind.addFuzzySet(new double[2] { 30.0, 45.0 }, "L", FuzzySet.FuzzySetType.LeftTrapeze);
      RSIind.addFuzzySet(new double[3] { 25.0, 50.0, 75.0 }, "M", FuzzySet.FuzzySetType.Triangle);
      RSIind.addFuzzySet(new double[2] { 55.0, 70.0 }, "H", FuzzySet.FuzzySetType.RightTrapeze);


      StockData sd = new StockData();
      sd.readFromFile(testDataFile);

      if (!nauczonoSiec)
      {
          //inicjalizacja wykresu
          initPriceGraph(sd.getSymbol(), sd.getFirstDate(), sd.getLastDate());
          initProfitGraph("Wartość portfela", sd.getFirstDate(), sd.getLastDate());
      }


      int end = (int)IndParams["n"];

      Best bst = new Best();

      for (int k = 0; ((k < end) && (sd.getNext() != -1)); k++)
      {
        bst.PushNext(sd.getClose(), sd.getDate());
        ROCindicator.pushNextDayData(sd.getOpen(), sd.getHigh(), sd.getLow(), sd.getClose(), sd.getVol());
        CCIindicator.pushNextDayData(sd.getOpen(), sd.getHigh(), sd.getLow(), sd.getClose(), sd.getVol());
        RSIindicator.pushNextDayData(sd.getOpen(), sd.getHigh(), sd.getLow(), sd.getClose(), sd.getVol());
        if (!nauczonoSiec) addNewCandle(sd.getDate(), sd.getHigh(), sd.getLow(), sd.getOpen(), sd.getClose(), sd.getVol());
     
      }

      int iter = 0;
      int i = 0;
      double pbSize = (sd.getSize() - end - 1) / 100.0;
      StringBuilder sb = new StringBuilder();
      while ((sd.getNext() != -1) && (iter < 100))
      {
        i++;

        bst.PushNext(sd.getClose(), sd.getDate());
        if (!nauczonoSiec) addNewCandle(sd.getDate(), sd.getHigh(), sd.getLow(), sd.getOpen(), sd.getClose(), sd.getVol());

        ROCindicator.pushNextDayData(sd.getOpen(), sd.getHigh(), sd.getLow(), sd.getClose(), sd.getVol());
        CCIindicator.pushNextDayData(sd.getOpen(), sd.getHigh(), sd.getLow(), sd.getClose(), sd.getVol());
        RSIindicator.pushNextDayData(sd.getOpen(), sd.getHigh(), sd.getLow(), sd.getClose(), sd.getVol());

        ROCind.fuzzify(ROCindicator.getValue());
        CCIind.fuzzify(CCIindicator.getValue());
        RSIind.fuzzify(RSIindicator.getValue());

        FuzzyAssociativeMemory fam1 = new FuzzyAssociativeMemory(ROCind, CCIind);
        FuzzyAssociativeMemory fam2 = new FuzzyAssociativeMemory(CCIind, RSIind);
        fam1.reason();
        fam2.reason();

        //tutaj chce podac wartosci na wejscia
        double v1 = fam1.defuzzify();
        double v2 = fam2.defuzzify();
        n.MakeDecision(v1,v2);
        //tutaj chce otrzymac wynik
        double r = n.getDecision;

        if (r > 0)
        {
          int sn = Math.Abs((int)((0.2 * r * cash) / sd.getClose()));
          sharesNumber += sn;
          cash -= sn * sd.getClose();
          cash -= 0.003 * sn * sd.getClose(); //prowizja 0.3%
          sb.AppendLine(sd.getDate().ToLongDateString() + ": Zakup " + sn + " akcji za " + sd.getClose());
          dgvPositions.Rows[0].Cells[0].Value = sd.getSymbol();
          dgvPositions.Rows[0].Cells[1].Value = sharesNumber;
          dgvPositions.Rows[0].Cells[2].Value = sharesNumber * sd.getClose();
          dgvPositions.Rows[1].Cells[0].Value = "Gotówka";
          dgvPositions.Rows[1].Cells[1].Value = "";
          dgvPositions.Rows[1].Cells[2].Value = Math.Round(cash, 2);
        }
        else if (r < 0) 
        {
          int sn = (int)(-0.2 * r * sharesNumber);
          if (sn > sharesNumber)
            sn = sharesNumber;

          sharesNumber -= sn;
          cash += sn * sd.getClose();
          cash -= 0.003 * sn * sd.getClose();
          sb.AppendLine(sd.getDate().ToLongDateString() + ": Sprzedaż: " + sn + " akcji za " + sd.getClose());
          dgvPositions.Rows[0].Cells[0].Value = sd.getSymbol();
          dgvPositions.Rows[0].Cells[1].Value = sharesNumber;
          dgvPositions.Rows[0].Cells[2].Value = sharesNumber * sd.getClose();
          dgvPositions.Rows[1].Cells[0].Value = "Gotówka";
          dgvPositions.Rows[1].Cells[1].Value = "";
          dgvPositions.Rows[1].Cells[2].Value = Math.Round(cash, 2);
        }

        addNewProfitPoint(sd.getDate(), cash + sharesNumber * sd.getClose());
        if (i % 100 == 0)
        {
          Console.WriteLine(sb.ToString());
          sb.Remove(0, sb.Length);
        }
        //iter++;
        int pbValue = (int)(i / pbSize);
        if (pbValue <= 100)
          pb.Value = pbValue;
      }

      bst.CalculateBest();

      Console.WriteLine(sb.ToString());
      lblEndPortfolioValue.Text = "Końcowa wartość portfela: " + Math.Round((cash + sharesNumber * sd.getLastClose()), 2).ToString() + "PLN";
      lblPL.Text = "Zysk/Strata: " + Math.Round((((cash + sharesNumber * sd.getLastClose()) - initialCash) / initialCash * 100.0), 2) + "%";
      lblBuyHold.Text = "Strategia Buy && Hold: " + Math.Round(((sd.getLastClose() - sd.getCloseForDay((int)IndParams["n"])) / sd.getCloseForDay((int)IndParams["n"]) * 100), 2) + "%";

      Console.WriteLine("Najlepsze rozwiązanie: {0} kup akcje za {1} i sprzedaj {2} za {3} zyskujac {4}%",
                 bst.Buy.XTime, bst.Buy.XValue, bst.Sell.XTime, bst.Sell.XValue, Math.Round(bst.Profit, 2));
       */
    }

    private void profitChart_ScrollEvent(object sender, ScrollEventArgs e)
    {
      profitChart.AxisChange();
      profitChart.Invalidate();
      priceChart.GraphPane.XAxis.Scale.Min = profitChart.GraphPane.XAxis.Scale.Min;
      priceChart.GraphPane.XAxis.Scale.Max = profitChart.GraphPane.XAxis.Scale.Max;
      priceChart.AxisChange();
      priceChart.Invalidate();
    }

    private void profitChart_ZoomEvent(ZedGraphControl sender, ZoomState oldState, ZoomState newState)
    {
      priceChart.GraphPane.XAxis.Scale.Min = profitChart.GraphPane.XAxis.Scale.Min;
      priceChart.GraphPane.XAxis.Scale.Max = profitChart.GraphPane.XAxis.Scale.Max;
      priceChart.AxisChange();
      priceChart.Invalidate();
    }

    private void priceChart_ZoomEvent(ZedGraphControl sender, ZoomState oldState, ZoomState newState)
    {
      profitChart.GraphPane.XAxis.Scale.Min = priceChart.GraphPane.XAxis.Scale.Min;
      profitChart.GraphPane.XAxis.Scale.Max = priceChart.GraphPane.XAxis.Scale.Max;
      profitChart.AxisChange();
      profitChart.Invalidate();
    }

    private void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
    {
        
        if (n != null) n.SaveNeuralNet(Path.GetDirectoryName(Application.ExecutablePath) + "/Default.neural");
    }

    private void LoadNNFromFile_Click(object sender, EventArgs e)
    {
        OpenFileDialog d = new OpenFileDialog();
        d.Title = "Wybierz konfigurację sieci neuronowej";
        d.InitialDirectory = Directory.GetCurrentDirectory() + "\\test";
        d.Filter = "Pliki Neural (*neural)|*.neural";
        if (d.ShowDialog() != DialogResult.OK)
            return;

        n = new NNStockMarket(d.FileName);
    }

    private void saveNNToFile_Click(object sender, EventArgs e)
    {
        if (n == null) return;
        SaveFileDialog d = new SaveFileDialog();
        d.Title = "Zapisz konfigurację sieci neuronowej";
        d.InitialDirectory = Path.GetDirectoryName(Application.ExecutablePath);
        d.Filter = "Pliki Neural (*neural)|*.neural";
        if (d.ShowDialog() != DialogResult.OK) return;

         n.SaveNeuralNet(d.FileName);
    }

    private void konsolaToolStripMenuItem_Click(object sender, EventArgs e)
    {
        if (konsolaToolStripMenuItem.Checked)
            horizontalSplitContainer.Panel2Collapsed = false;
        else
            horizontalSplitContainer.Panel2Collapsed = true;
    }

    private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
    {
        Help h = new Help();
        h.Show();
    }

    private void pomocDoProgramuToolStripMenuItem_Click(object sender, EventArgs e)
    {
        UsingHelp uh = new UsingHelp();
        uh.Show();
    }

    private void expertSystemSettings_Click(object sender, EventArgs e)
    {
        ExpertSet ExSet = new ExpertSet();
        ExSet.ShowDialog();
    }

  }

  public class StringRedir : StringWriter
  { // Redirecting Console output to RichtextBox
    private RichTextBox outBox;

    public StringRedir(ref RichTextBox textBox)
    {
      outBox = textBox;
    }

    public override void WriteLine(string x)
    {
      outBox.Text += x + "\n";
      outBox.Refresh();
      outBox.SelectionLength = 0;
      outBox.SelectionStart = outBox.Text.Length;
      outBox.ScrollToCaret();
    }
  }


}
